class KPromise {
    constructor(handle) {
        // $emit data 
        this['[[PromiseState]]'] = 'pending';
        this['[[PromiseResult]]'] = undefined;
        // this.resolveFn = undefined;
        // this.rejectFn = undefined;
        this.resolveQueue = [];
        this.rejectQueue = [];
        // handle((val)=>{
        //     this['[[PromiseState]]'] = 'fulfilled';
        //     this['[[PromiseResult]]'] = val;
        // },(err)=>{
        //     this['[[PromiseState]]'] = 'rejected';
        //     this['[[PromiseResult]]'] = err;
        // });
        handle(this.#resolve.bind(this), this.#reject.bind(this));
    }
    #resolve(val) {
        // console.log(this);
        this['[[PromiseState]]'] = 'fulfilled';
        this['[[PromiseResult]]'] = val;
        const run = () => {
            // this.resolveFn(val);
            let cb;
            while (cb = this.resolveQueue.shift()) {
                cb && cb(val);
            }
        }
        // setTimeout(run);
        let ob = new MutationObserver(run);
        ob.observe(document.body, {
            attributes: true
        })
        document.body.setAttribute("kkb", "value");
    }
    #reject(err) {
        this['[[PromiseState]]'] = 'rejected';
        this['[[PromiseResult]]'] = err;
        // this.rejectFn(err);
        const run = () => {
            // this.rejectFn(err);
            let cb;
            while (cb = this.rejectQueue.shift()) {
                cb && cb(err);
            }
        }
        // setTimeout(run);
        let ob = new MutationObserver(run);
        ob.observe(document.body, {
            attributes: true
        })
        document.body.setAttribute("kkb", "value");
    }
    then(onResolved, onRejected) {
        // if(this['[[PromiseState]]']==='fulfilled'){
        //     onResolved(this['[[PromiseResult]]'])
        // }
        // 保存 onResolved、onRejected；
        // this.resolveFn = onResolved;
        // this.rejectFn = onRejected;
        return new KPromise((reslove, reject) => {
            // onResolved();
            let resolveFn = (val) => {
                let res = onResolved && onResolved(val);
                if(res instanceof KPromise){
                    // 返还的一个promise对象，取出值
                    // res.then(result=>{
                    //     reslove(result);
                    // })
                    res.then(reslove);
                }else{
                    // 普通值
                    reslove(res);
                }
            }
            this.resolveQueue.push(resolveFn);
            // this.rejectQueue.push(onRejected);
            let rejectFn = (err) => {
                onRejected && onRejected(err);
                reject(err);
            }
            this.rejectQueue.push(rejectFn);
        })
    }
    static resolve(val){
        return new KPromise(resolve=>{
            resolve(val);
        })
    }
    static reject(err){
        return new KPromise((resolve,reject)=>{
            reject(err);
        })
    }
    static race(lists){
        return new KPromise((resolve,reject)=>{
            lists.forEach(item=>{
                item.then(res=>{
                    resolve(res);
                },err=>{
                    reject(err); 
                })
            })
        })
    }
    static allSettled(lists){
        let resArr = new Array(lists.length);
        let num = 0
        return new KPromise(resolve=>{
            lists.forEach((item,key)=>{
                let obj = {};
                item.then(res=>{
                     obj['status'] = "fulfilled";
                     obj['value'] = res;
                     resArr[key] = obj;
                     num++;
                     if(num>=lists.length){
                        resolve(resArr);
                     }
                },err=>{
                    obj['status'] = "rejected";
                    obj['reason'] = err;
                    resArr[key] = obj;
                    num++;
                    if(num>=lists.length){
                        resolve(resArr);
                     }
                })
            })
        })

    }
    static all(lists){
        let resArr = []
        let num = 0
        return new KPromise(res=>{
            lists.forEach(item=>{
                item.then(res=>{
                     resArr.push(res)
                     num++;
                     if(resArr.length === lists.length){
                        resolve(resArr);
                     }
                })
            })
        })
    }

    catch(cb){
        this.then(undefined,cb);
    }
    finally(cb){
        this.then(cb,cb)
    }

}